﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ApprovalFlow;
using ApprovalFlow.Interface;
using ApprovalFlow.Models;
using ApprovalFlow.Services;
using ApprovalFlow.Services.BackgroundTasks;

namespace Microsoft.Extensions.DependencyInjection
{
    public static class ServiceCollectionExtensions
    {
        /// <summary>
        /// 添加工作流的服务容器。
        /// </summary>
        /// <param name="services"></param>
        /// <param name="setupAction"></param>
        /// <returns></returns>
        public static IServiceCollection AddWorkflow(this IServiceCollection services, Action<WorkflowOptions> setupAction = null)
        {
            if (services.Any(x => x.ServiceType == typeof(WorkflowOptions)))
                throw new InvalidOperationException("Workflow services already registered");

            var options = new WorkflowOptions(services);
            setupAction?.Invoke(options);

            services.AddSingleton<WorkflowOptions>(options);
            services.AddSingleton<IPersistenceProvider>(options.PersistanceFactory);
            services.AddSingleton<IWorkflowRepository>(options.PersistanceFactory);
            services.AddSingleton<ISubscriptionRepository>(options.PersistanceFactory);
            services.AddSingleton<IEventRepository>(options.PersistanceFactory);
            services.AddSingleton<IQueueProvider>(options.QueueFactory);            
            services.AddSingleton<IWorkflowHost, WorkflowHost>();

            services.AddSingleton<IWorkflowRegistry, WorkflowRegistry>();
            services.AddTransient<IDateTimeProvider, DateTimeProvider>();
            
            services.AddTransient<IExecutionResultProcessor, ExecutionResultProcessor>();
            services.AddTransient<IExecutionPointerFactory, ExecutionPointerFactory>();

            services.AddSingleton<ISingletonMemoryProvider, MemoryPersistenceProvider>();
            services.AddTransient<IUserProvider, SingelUserProvider>();

            services.AddSingleton<IApprovalExecutor, ApprovalExecutor>();
            services.AddTransient<IWorkflowExecutor, WorkflowExecutor>();

            services.AddTransient<ApprovalFlow.Primitives.Approval>();
            return services;
        }
    }
}
